﻿#include "tablepdf.h"

#include <QImage>
#include <QPixmap>
#include <QPainter>
#include <QDateTime>
#include <cstdio>

TablePdf::TablePdf() {
    m_pdf = HPDF_New(NULL, NULL);
    createPage();
    HPDF_UseCNSFonts(m_pdf);
    HPDF_UseCNTFonts(m_pdf);
    HPDF_UseCNSEncodings(m_pdf);
    HPDF_UseCNTEncodings(m_pdf);
    m_font = HPDF_GetFont(m_pdf, "SimHei", "GB-EUC-H");
    m_firstPageTabY = 0;
    setPageMargin(0, 0, 0, 0);
}

TablePdf::~TablePdf()
{
    HPDF_Free(m_pdf);
}

Pos TablePdf::switchHaruToCss(Pos haruPos)
{
    return { haruPos.x  - m_pageLeft, m_pageHeight - haruPos.y - m_pageTop };
}

Pos TablePdf::switchCssToHaru(Pos cssPos)
{
    return { cssPos.x + m_pageLeft, m_pageHeight - (cssPos.y + m_pageTop)};
}

void TablePdf::setPageMargin(int top, int bottom, int left, int right)
{
    m_pageTop = top;
    m_pageBottom = bottom;
    m_pageLeft = left;
    m_pageRight = right;
    m_tableWidth = m_pageWidth - left - right;
    m_tableHeight = m_pageHeight - top - bottom;
}

void TablePdf::createPage()
{
    HPDF_Page page = HPDF_AddPage(m_pdf);
    HPDF_Page_SetSize(page, HPDF_PAGE_SIZE_A4, HPDF_PAGE_PORTRAIT);
    m_pageList.push_back(page);
    m_pageWidth = HPDF_Page_GetWidth(page);
    m_pageHeight = HPDF_Page_GetHeight(page);
}

void TablePdf::setPageProperty(HPDF_PageSizes size, HPDF_PageDirection direction) {
    pageSize = size;
    pageDirection = direction;
}


bool TablePdf::setPassword(QString ownerPasswd, QString userPasswd) {
    return HPDF_SetPassword(m_pdf, ownerPasswd.toStdString().c_str(), userPasswd.toStdString().c_str());
}

void TablePdf::SetPermission(HPDF_UINT permission)
{
    HPDF_SetPermission (m_pdf, permission);
    HPDF_SetEncryptionMode(m_pdf, HPDF_ENCRYPT_R3, 6);
}

int TablePdf::watermarkDraw(string imagePath, double trans)
{
    // 制作逆时针旋转45°水印
    QImage image(QString::fromStdString(imagePath));
    if (image.isNull()) {
        return -1;
    }
    QPixmap pix = QPixmap::fromImage(image);
    QPixmap tmpPix(pix.size());
    tmpPix.fill(Qt::transparent);
    QPainter p1(&tmpPix);
    p1.setCompositionMode(QPainter::CompositionMode_Source);
    p1.drawPixmap(0, 0, pix);
    p1.setCompositionMode(QPainter::CompositionMode_DestinationIn);
    //200表示透明度，数值0表示完全透明，数值255表示不透明
    p1.fillRect(tmpPix.rect(), QColor(0, 0, 0, (int)(255 * trans)));
    p1.end();
    auto image1 = tmpPix.toImage().transformed(QTransform().rotate(315));
    image1.save("image.png");

    // 在pdf上添加水印
    HPDF_Image watermark = HPDF_LoadPngImageFromFile(m_pdf, "image.png");

    HPDF_UINT markWidth = HPDF_Image_GetWidth(watermark);
    HPDF_UINT markHeight = HPDF_Image_GetHeight(watermark);

    for (auto& page : m_pageList){

        for (int i = 100; i < m_pageHeight; i += m_pageHeight / 2) {
            for (int j = - (int)(markWidth / 2); j < m_pageWidth; j += m_pageWidth/ 2) {
                auto status = HPDF_Page_DrawImage(page, watermark, j, i, markWidth, markHeight);
                if (HPDF_OK != status) {
                    std::cout << "图片加载失败" << std::endl;
                    return status;
                }
            }
        }
    }
    if (remove("image.png") != 0) { // 尝试删除图片
        std::cout << "删除图片失败";
    }

    return HPDF_OK;
}

void TablePdf::drawLine(int pageNum, HPDF_REAL x1, HPDF_REAL y1, HPDF_REAL x2, HPDF_REAL y2)
{
    drawLine(pageNum, {x1, y1}, {x2, y2});
}

void TablePdf::drawLine(int pageNum, Pos p1, Pos p2)
{
    auto HaruPos1 = switchCssToHaru(p1);
    auto HaruPos2 = switchCssToHaru(p2);

    if (pageNum < 0 && pageNum >= m_pageList.size()) {
        return;
    }
    auto& page = m_pageList[pageNum];
    HPDF_Page_MoveTo(page, HaruPos1.x, HaruPos1.y);
    HPDF_Page_LineTo(page, HaruPos2.x, HaruPos2.y);
    HPDF_Page_Stroke(page);
}

void TablePdf::drawText(int pageNum, Rect textRect, string text, HPDF_TextAlignment align)
{
    if (pageNum < 0 && pageNum >= m_pageList.size()) {
        return;
    }
    drawText(pageNum, textRect.p1, textRect.p2, text, align);
}

void TablePdf::drawText(int pageNum, Pos CssPos, Pos sizePos, string text, HPDF_TextAlignment align)
{
    if (pageNum < 0 && pageNum >= m_pageList.size()) {
        return;
    }
    auto& page = m_pageList[pageNum];
    auto HaryPos1 = switchCssToHaru(CssPos);
    auto HaryPos2 = switchCssToHaru(sizePos);
    HPDF_Page_BeginText(page);
    HPDF_Page_TextRect(page, HaryPos1.x, HaryPos1.y, HaryPos2.x, HaryPos2.y, text.c_str(), align, NULL);
    HPDF_Page_EndText(page);
}

void TablePdf::addTitle(string titleText, string peopleText)
{
    auto& page = m_pageList[0];

    HPDF_Page_SetRGBStroke(page, 0, 0, 1);
    HPDF_Page_SetLineWidth(page, 2);
    drawLine(0, 0, 0, m_tableWidth, 0);

    HPDF_Page_SetRGBFill(page, 1, 0, 0);
    HPDF_Page_SetFontAndSize(page, m_font, 28);
    drawText(0, Pos{0, 10}, Pos{m_tableWidth, 30}, titleText, HPDF_TALIGN_CENTER);

    HPDF_Page_SetRGBFill(page, 0, 0, 0);
    HPDF_Page_SetFontAndSize(page, m_font, 15);
    drawText(0, Pos{0, 40}, Pos{m_tableWidth, 60}, peopleText, HPDF_TALIGN_RIGHT);

    QString currDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    HPDF_Page_SetFontAndSize(page, m_font, 15);
    drawText(0, Pos{0, 60}, Pos{m_tableWidth, 70}, currDateTime.toStdString(), HPDF_TALIGN_RIGHT);

    m_firstPageTabY = 80;
}

bool TablePdf::getTableCsv(const char *csvFileName)
{
    std::ifstream csv_data;
    csv_data.open(csvFileName, ios::in);

    if (!csv_data.is_open()) {
        std::cout << "csv文件无法打开";
        return false;
    }
    std::string line, word;
    std::istringstream strin;

    // 读取表头
    std::getline(csv_data, line);
    strin.str(line);
    while (std::getline(strin, word, ','))
    {
        m_header.push_back(word);
    }

    // 按行读取数据
    while (getline(csv_data, line))
    {
        std::vector<std::string> words;
        strin.clear();
        strin.str(line);

        //将字符串流strin中的字符读到字符串数组words中，以逗号为分隔符
        while (std::getline(strin, word, ',')) {
            words.push_back(word);
        }
        m_tableData.push_back(words);

    }
    csv_data.close();

    m_rowCount = m_tableData.size();
    m_colCount = m_header.size();

    computeTableSize();

    return true;
}

void TablePdf::drawTable()
{
    if (m_tableData.size() == 0) {
        return;
    }

    int dataRow = 0;
    m_alignment = HPDF_TALIGN_CENTER;

    for (int i = 0; i < m_pageCount; ++i) {

        auto& page = m_pageList[i];
        HPDF_Page_SetFontAndSize(page, m_font, 12);
        HPDF_Page_SetRGBStroke(page, 0, 0, 0);
        HPDF_Page_SetLineWidth(page, 1);
        // 创建透明画布并绘制
        HPDF_REAL x = 0;
        HPDF_REAL currentRowSize = ((i == 0) ? m_firstPageRowSize: m_commonPageRowSize);
        HPDF_REAL y = ((i == 0) ? m_firstPageTabY : 0);

        // 计算最后一页数据剩多少行
        if (i == m_pageCount - 1) {
            currentRowSize = m_rowCount - dataRow + 1; // +1 是表头所占的一行
        }

        // 垂直线
        drawLine(i, 0, y, 0, y + currentRowSize * m_cellHeight);  // 最左侧线
        for (int c = 0; c < m_cellWidths.size(); ++c) {
            x += m_cellWidths[c];
            drawLine(i, x, y, x, y + currentRowSize * m_cellHeight);
        }

        // 水平线
        drawLine(i,0, y, m_tableWidth, y);             // 最顶部线
        for (int r = 0; r < currentRowSize; ++r) {
            y += m_cellHeight;
            drawLine(i,0, y, m_tableWidth, y);
        }

        // 绘画表头
        x = 0;
        y = ((i == 0) ? m_firstPageTabY : 0);

        for (int c = 0; c < m_header.size(); c++) {
            Rect rect({x, y + m_tableMargin}, {x + m_cellWidths[c], y + m_cellHeight});
            drawText(i, rect, m_header[c].c_str() ,m_alignment);
            x += m_cellWidths[c];
        }
        y += m_cellHeight;

        // 绘画数据
        for (int r = 0; r < currentRowSize - 1 && dataRow < m_rowCount; ++r) {
            x = 0;
            for (int c = 0; c < m_colCount; ++c) {
                string text = m_tableData[dataRow][c];
                Rect rect(Pos{x, y + m_tableMargin}, Pos{x + m_cellWidths[c], y + m_cellHeight});
                drawText(i, rect, text.c_str(), m_alignment);
                x += m_cellWidths[c];
            }
            y += m_cellHeight;
            dataRow++;
        }
    }
}

void TablePdf::savePdf(string pdfName)
{
    QString name = QString::fromStdString(pdfName).split(".").at(0) + ".pdf";
    HPDF_SaveToFile(m_pdf, name.toStdString().c_str());

    if (remove(pdfName.c_str()) != 0) { // 尝试删除文件
        std::cout << "删除csv文件失败";
    }
}

void TablePdf::computeTableSize()
{
    // A4中表格固定尺寸
    const HPDF_REAL a4Width = m_tableWidth;
    const HPDF_REAL a4Height = m_tableHeight;

    // 计算每列最大文本宽度
    vector<HPDF_REAL> colContentWidths;

    HPDF_REAL font_size = 12.0;

    m_tableMargin = 3; // 边距

    for (int c = 0; c < m_colCount; ++c) {

        string headerItem = m_header[c];
        HPDF_REAL maxWidth =  headerItem.size();

        for (int r = 0; r < m_rowCount; ++r) {
            string text = m_tableData[r][c];
            HPDF_REAL  textWidth =  text.size();
            maxWidth = (maxWidth > textWidth ? maxWidth : textWidth);
        }
        colContentWidths.push_back(maxWidth);
    }

    // 计算总内容宽度和列宽比例
    HPDF_REAL totalContentWidth = accumulate(colContentWidths.begin(), colContentWidths.end(), 0.0);
    for (HPDF_REAL w : colContentWidths) {
        m_cellWidths.push_back((w / totalContentWidth) * a4Width);
    }
    totalContentWidth = accumulate(colContentWidths.begin(), colContentWidths.end(), 0.0);

    m_cellHeight = font_size + m_tableMargin * 2;

    m_firstPageRowSize = (a4Height - m_firstPageTabY) / m_cellHeight;
    m_commonPageRowSize = a4Height / m_cellHeight;

    m_firstPageDataRowSize = m_firstPageRowSize - 1;
    m_commonPageDataRowSize = m_commonPageRowSize - 1;

    m_pageCount = 1;
    if (m_rowCount > m_firstPageDataRowSize){
        m_pageCount += (m_rowCount - m_firstPageDataRowSize) / m_commonPageDataRowSize;
        if (((m_rowCount - m_firstPageDataRowSize) % m_commonPageDataRowSize) != 0){
            ++ m_pageCount;
        }
    }

    if (m_pageCount > 1) {
        for (int i = 1; i < m_pageCount; i++){
            createPage();
        }
    }
}